package com.ma.a12;


import com.ma.a12.A12.Foo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * @ClassName $Proxy0
 * @Author: mayongqiang
 * @DATE 2022/4/10 12:24
 * @Description: 模仿JDK代理类
 */
// 模拟代理类也要实现接口

public class $Proxy0  extends Proxy implements Foo {
    //private InvocationHandler h;

    public $Proxy0(InvocationHandler h) {
        //this.h = h;
        super(h);
    }

    @Override
    public void foo() {
        /*
        1、代理类的行为不能写死，具体行为不能放在代理类内部来做
                ----->  所以将其改为抽象方法  由外部实现它提供具体的实现
           理解：1代理首先需要与目标实现共同的接口,
                2为了让代理的方法内逻辑不要固定死，需要设计接口回调抽象操作  invoke逻辑不能固定死
                3事先准备好接口的foo方法对象方法对象，在invoke中具体根据目标对象反射调用真正的foo方法
         */
        try {
            //Method foo = Foo.class.getDeclaredMethod("foo");
            h.invoke(this, foo, new Object[0]);
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    /*
    处理try-catch 异常需要返回值的问题
    1、运行时异常 Error | RuntimeException  直接抛出无需处理
    2、检查异常 Throwable 将其转换为运行时异常抛出

     */
    @Override
    public int bar() {
        try {
            //Method bar = Foo.class.getDeclaredMethod("bar");
            return (Integer) h.invoke(this, bar, new Object[0]);
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }


    /*
    每调用一次代理类的方法时都需要获取一次方法对象，冗余操作
     写在静态代码块中 保证制备初始化一次
     */
    static Method foo;
    static Method bar;

    static {
        try {
            foo = Foo.class.getDeclaredMethod("foo");
            bar = Foo.class.getDeclaredMethod("bar");
        } catch (NoSuchMethodException e) {
            // 静态代码块中的异常必须处理，要抛出
            //e.printStackTrace();
            throw new NoSuchMethodError(e.getMessage());
        }
    }


}
